home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / New System Software Extensions / OpenDoc A6 / OpenDoc Parts Framework / OPF / Found / FWExcLib / Sources / FWExcRun.cpp < prev    next >
Encoding:
Text File  |  1994-04-21  |  13.0 KB  |  393 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWExcRun.cpp
  4. //    Release Version:    $ 1.0d1 $
  5. //
  6. //    Creation Date:        3/28/94
  7. //
  8. //    Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #include <string.h>
  13.  
  14. #ifndef   FWEXCRUN_H
  15. #include "FWExcRun.h"
  16. #endif
  17.  
  18. #ifndef   FWDELSTA_H
  19. #include "FWDelSta.h"
  20. #endif
  21.  
  22. #ifndef   FWTRYBLO_H
  23. #include "FWTryBlo.h"
  24. #endif
  25.  
  26. #ifndef   FWPRIDEB_H
  27. #include "FWPriDeb.h"
  28. #endif
  29.  
  30. #ifndef   FWPRIMEM_H
  31. #include "FWPriMem.h"
  32. #endif
  33.  
  34. #ifndef FWNEWHEL_H
  35. #include "FWNewHel.h"
  36. #endif
  37.  
  38. #ifndef   FWONSTAC_H
  39. #include "FWOnStac.h"
  40. #endif
  41.  
  42. #ifdef FW_BUILD_MAC
  43. #pragma segment BEL
  44. #endif
  45.  
  46. //========================================================================================
  47. //    Functions for "unexpected" and "terminate"
  48. //
  49. //        See ARM, Section 15.6
  50. //========================================================================================
  51.  
  52. extern "C" void abort ();
  53.  
  54. static void DefaultTerminate();
  55. static void DefaultUnexpected();
  56.  
  57. static void DefaultTerminate()
  58. {
  59.     abort();
  60. }
  61.  
  62. static void DefaultUnexpected()
  63. {
  64.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  65.     PFV pfCurrentTerminate = globals.gCurrentTerminate;
  66.     (*pfCurrentTerminate)();
  67. }
  68.  
  69. void terminate()
  70. {
  71.     FW_PRIV_DEBUGGER_BREAK();
  72.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  73.     PFV pfCurrentTerminate = globals.gCurrentTerminate;
  74.     (*pfCurrentTerminate)();
  75. }
  76.  
  77. void unexpected()
  78. {
  79.     FW_PRIV_DEBUGGER_BREAK();
  80.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  81.     PFV pfCurrentUnexpected = globals.gCurrentUnexpected;
  82.     (*pfCurrentUnexpected)();
  83. }
  84.  
  85. PFV set_terminate(PFV terminate)
  86. {
  87.     return _FW_CExceptionRuntime::SetTerminate(terminate);
  88. }
  89.  
  90. PFV set_unexpected(PFV unexpected)
  91. {
  92.     return _FW_CExceptionRuntime::SetUnexpected(unexpected);
  93. }
  94.  
  95. #ifdef FW_BUILD_WIN32S
  96. _FW_PrivIsOnStack(void * p)
  97. {
  98.     char localVar;
  99.     return &localVar <= p && p <= &localVar + 16000;
  100. }
  101. #endif
  102.  
  103. //========================================================================================
  104. // CLASS _FW_CExceptionRuntime
  105. //========================================================================================
  106.  
  107. //----------------------------------------------------------------------------------------
  108. // _FW_CExceptionRuntime::Initialize
  109. //----------------------------------------------------------------------------------------
  110. void _FW_CExceptionRuntime::Initialize(FW_SPrivExceptionGlobals& globals)
  111. {
  112. #ifdef FW_DEBUG
  113.     // verify our _FW_PrivIsOnStack routine
  114.     int local;
  115.     static int gGlobal;
  116.     void* code = (void*) _FW_CExceptionRuntime::Initialize;
  117.     FW_PRIV_ASSERT(_FW_PrivIsOnStack(&local));
  118.     FW_PRIV_ASSERT(!_FW_PrivIsOnStack(&gGlobal));
  119.     FW_PRIV_ASSERT(!_FW_PrivIsOnStack(code));
  120. #endif
  121.     
  122.     globals.gExceptionBufferSize = kDefaultExceptionBufferSize;
  123.     globals.gExceptionBuffer = ::FW_PrimitiveAllocateBlock(kDefaultExceptionBufferSize);
  124.     globals.gCurrentTerminate = DefaultTerminate;
  125.     globals.gCurrentUnexpected = DefaultUnexpected;
  126.     
  127. #ifdef FW_DEBUG
  128.     SetBreakOnThrow(NULL);
  129. #endif
  130. }
  131.  
  132. //----------------------------------------------------------------------------------------
  133. // _FW_CExceptionRuntime::Terminate
  134. //----------------------------------------------------------------------------------------
  135. void _FW_CExceptionRuntime::Terminate()
  136. {
  137.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  138.     ::FW_PrimitiveFreeBlock(globals.gExceptionBuffer);
  139. }
  140.  
  141. //----------------------------------------------------------------------------------------
  142. // _FW_CExceptionRuntime::SetTerminate
  143. //----------------------------------------------------------------------------------------
  144. PFV _FW_CExceptionRuntime::SetTerminate(PFV newTerminate)
  145. {
  146.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  147.     PFV oldTerminate = globals.gCurrentTerminate;
  148.     globals.gCurrentTerminate = newTerminate;
  149.     return oldTerminate;
  150. }
  151.  
  152. //----------------------------------------------------------------------------------------
  153. // _FW_CExceptionRuntime::SetUnexpected
  154. //----------------------------------------------------------------------------------------
  155. PFV _FW_CExceptionRuntime::SetUnexpected(PFV newUnexpected)
  156. {
  157.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  158.     PFV oldUnexpected = globals.gCurrentUnexpected;
  159.     globals.gCurrentUnexpected = newUnexpected;
  160.     return oldUnexpected;
  161. }
  162.  
  163. //----------------------------------------------------------------------------------------
  164. // _FW_CExceptionRuntime::CaughtException
  165. //----------------------------------------------------------------------------------------
  166. void _FW_CExceptionRuntime::CaughtException(FW_SPrivExceptionGlobals& globals, _FW_CException * caughtException)
  167. {
  168.     globals.gThrownException->Delete();
  169.     globals.gCaughtException = caughtException;
  170.     globals.gThrownException = NULL;
  171. }
  172.  
  173. //----------------------------------------------------------------------------------------
  174. // _FW_CExceptionRuntime::CaughtEverythingException
  175. //----------------------------------------------------------------------------------------
  176. void _FW_CExceptionRuntime::CaughtEverythingException(FW_SPrivExceptionGlobals& globals)
  177. {
  178.     globals.gCaughtException = globals.gThrownException;
  179.     globals.gThrownException = NULL;
  180. }
  181.  
  182. //----------------------------------------------------------------------------------------
  183. // _FW_CExceptionRuntime::CaughtNoInstanceException
  184. //----------------------------------------------------------------------------------------
  185. void _FW_CExceptionRuntime::CaughtNoInstanceException(FW_SPrivExceptionGlobals& globals)
  186. {
  187.     globals.gCaughtException = globals.gThrownException;
  188.     globals.gThrownException = NULL;
  189. }
  190.  
  191. //----------------------------------------------------------------------------------------
  192. // _FW_CExceptionRuntime::CaughtReferenceException
  193. //----------------------------------------------------------------------------------------
  194. void _FW_CExceptionRuntime::CaughtReferenceException(FW_SPrivExceptionGlobals& globals)
  195. {
  196.     globals.gCaughtException = globals.gThrownException;
  197.     globals.gThrownException = NULL;
  198. }
  199.  
  200. //----------------------------------------------------------------------------------------
  201. // _FW_CExceptionRuntime::PrimitiveThrow
  202. //----------------------------------------------------------------------------------------
  203. void _FW_CExceptionRuntime::PrimitiveThrow(const _FW_CException & thrownException)
  204. {
  205.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  206.  
  207.     // Should never have an exception on the way in
  208.     FW_PRIV_ASSERT(globals.gThrownException == NULL);
  209.     
  210.     _FW_CTryBlockContext *context = globals.gCurrentContext;
  211.     FW_PRIV_ASSERT(context!=NULL);
  212.     if (context->fPriorContext == NULL)
  213.     {
  214.         terminate();
  215.         abort(); // Terminate should never return
  216.     }
  217.  
  218.     if (_FW_CDeleteStack::IsClassExpectedInContext(context, thrownException.PrivVirtualGetClassInfo()))
  219.     {
  220.         // If someone had caught an exception delete that exception
  221.         // because we are going to bypass the destructor for it.
  222.         if (globals.gCaughtException != NULL)
  223.         {
  224.             globals.gCaughtException->Delete();
  225.             globals.gCaughtException = 0;
  226.         }
  227.  
  228.         // Copy the original into our exception buffer
  229.         thrownException.Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
  230.  
  231.         // We have a thrown exception so point gThrownException at it.
  232.         globals.gThrownException = (_FW_CException*)globals.gExceptionBuffer;
  233.  
  234.         // We have copied the original so delete it.
  235.         ((_FW_CException &)thrownException).Delete();
  236.  
  237.         DeleteObjectsInContextAndJump(globals, context);
  238.     }
  239.     else
  240.     {
  241.         unexpected();
  242.     }
  243. }
  244.  
  245. //----------------------------------------------------------------------------------------
  246. // _FW_CExceptionRuntime::PrimitiveThrowSame
  247. //----------------------------------------------------------------------------------------
  248. void _FW_CExceptionRuntime::PrimitiveThrowSame()
  249. {
  250.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  251.  
  252.     FW_PRIV_ASSERT(globals.gCaughtException != NULL);
  253.     if (globals.gCaughtException == NULL)
  254.     {
  255.         abort();            // Can't throwsame if nothing is currently caught
  256.     }
  257.  
  258.     _FW_CTryBlockContext * context = globals.gCurrentContext;
  259.     FW_PRIV_ASSERT(context != NULL);
  260.     if (context->fPriorContext == NULL)
  261.     {
  262.         terminate();
  263.         abort();            // Terminate should never return but if it does we will abort
  264.     }
  265.  
  266.     _FW_CException *caughtException = globals.gCaughtException;
  267.  
  268.     if (_FW_CDeleteStack::IsClassExpectedInContext(context, caughtException->PrivVirtualGetClassInfo()))
  269.     {
  270.         if (caughtException != (_FW_CException *)globals.gExceptionBuffer)
  271.         {
  272.             // The exception is in the stack frame so copy it to our exception buffer,
  273.             // delete the original and then pass the copy along.
  274.             caughtException->Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
  275.             caughtException->Delete();
  276.             globals.gThrownException = (_FW_CException*)globals.gExceptionBuffer;
  277.         }
  278.         else
  279.         {
  280.             // The exception is already in our buffer
  281.             globals.gThrownException = (_FW_CException*)globals.gCaughtException;
  282.         }
  283.  
  284.         globals.gCaughtException = 0;
  285.  
  286.         DeleteObjectsInContextAndJump(globals, context);
  287.     }
  288.     else
  289.     {
  290.         unexpected();
  291.     }
  292. }
  293.  
  294.  
  295. //----------------------------------------------------------------------------------------
  296. // _FW_CExceptionRuntime::Throw
  297. //----------------------------------------------------------------------------------------
  298. void _FW_CExceptionRuntime::Throw(const _FW_CException & thrownException)
  299. {
  300.     PrimitiveThrow(thrownException);
  301. }
  302.  
  303. //----------------------------------------------------------------------------------------
  304. // _FW_CExceptionRuntime::ThrowSame
  305. //----------------------------------------------------------------------------------------
  306. void _FW_CExceptionRuntime::ThrowSame()
  307. {
  308.     PrimitiveThrowSame();
  309. }
  310.  
  311. //----------------------------------------------------------------------------------------
  312. // _FW_CExceptionRuntime::ThrowConstructor
  313. //----------------------------------------------------------------------------------------
  314. void _FW_CExceptionRuntime::ThrowConstructor(_FW_CException & thrownException)
  315. {
  316.     PrimitiveThrow(thrownException);
  317. }
  318.  
  319. //----------------------------------------------------------------------------------------
  320. // _FW_CExceptionRuntime::ThrowSameConstructor
  321. //----------------------------------------------------------------------------------------
  322. void _FW_CExceptionRuntime::ThrowSameConstructor()
  323. {
  324.     PrimitiveThrowSame();
  325. }
  326.  
  327. //----------------------------------------------------------------------------------------
  328. // _FW_CExceptionRuntime::KeepThrowing
  329. //----------------------------------------------------------------------------------------
  330. void _FW_CExceptionRuntime::KeepThrowing(FW_SPrivExceptionGlobals& globals)
  331. {
  332.     _FW_CTryBlockContext *context = globals.gCurrentContext;
  333.     FW_PRIV_ASSERT(context!=NULL);
  334.     if (_FW_CDeleteStack::IsClassExpectedInContext(context, globals.gThrownException->PrivVirtualGetClassInfo()))
  335.     {
  336.         DeleteObjectsInContextAndJump(globals, context);
  337.     }
  338.     else
  339.     {
  340.         unexpected();
  341.     }
  342. }
  343.  
  344.  
  345. //----------------------------------------------------------------------------------------
  346. // _FW_CExceptionRuntime::ResetExceptionBufferSize
  347. //----------------------------------------------------------------------------------------
  348. void _FW_CExceptionRuntime::ResetExceptionBufferSize(size_t newSize)
  349. {
  350.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  351.     void *p = ::FW_PrimitiveResizeBlock(globals.gExceptionBuffer, newSize);
  352.     FW_PRIV_ASSERT(p != NULL);
  353.     globals.gExceptionBuffer = p;
  354.     globals.gExceptionBufferSize = newSize;
  355. }
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // _FW_CExceptionRuntime::DeleteObjectsInContextAndJump
  359. //----------------------------------------------------------------------------------------
  360. void _FW_CExceptionRuntime::DeleteObjectsInContextAndJump(FW_SPrivExceptionGlobals& globals, 
  361.                                                         _FW_CTryBlockContext * context)
  362. {
  363. #ifdef FW_DEBUG
  364.     _FW_CException *thrownException = globals.gThrownException;
  365.     FW_ClassReference breakExceptionKind = globals.gBreakExceptionKind;
  366.     if (breakExceptionKind!=NULL && thrownException->__IsKindOf(breakExceptionKind))
  367.         FW_PRIV_DEBUGGER_STRING("Throwing an exception");
  368. #endif    
  369.     
  370.    _FW_CDeleteStack::PopOffAndDeleteObjectsInContext(globals, context);
  371.  
  372.     jmp_buf *jumpBuffer = context->fJumpBuffer;
  373. //    context->_FW_CTryBlockContext::~_FW_CTryBlockContext();
  374.     context->~_FW_CTryBlockContext();
  375.      ::longjmp(*jumpBuffer, 1);
  376. }
  377.  
  378.  
  379. //----------------------------------------------------------------------------------------
  380. // _FW_CExceptionRuntime::EndConstructor
  381. //----------------------------------------------------------------------------------------
  382. void _FW_CExceptionRuntime::EndConstructor(_FW_CAutoDestructObject *object, size_t size)
  383. {
  384.     if (_FW_PrivIsOnStack(object))
  385.         _FW_CDeleteStack::Push(object);
  386.     else
  387.     {
  388.         _FW_CPrivNewHelper *helper = _FW_CPrivNewHelper::TopNewHelper();
  389.         if (helper!=NULL && helper->IsWatching(object))
  390.             helper->UpdateForEndConstructor(object, size);
  391.     }
  392. }
  393.